<?php

namespace App\Models;

use Exception;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Cache;

/*电子书资源章节管理model*/

class ResourceEbookChapterInfo extends BaseModel
{
    use HasFactory;

    const CREATED_AT = 'create_time';
    const UPDATED_AT = 'change_time';


    protected $table = 'resource_ebook_chapter_info';


    /**
     * 获取电子书章节列表
     * @param ebook_id 电子书id
     */
    public function getChapterList($ebook_id, $limit = 10)
    {
        $field = ['id', 'chapter_name', 'chapter_src'];
        $res = $this->select($field)
            ->where('ebook_id', $ebook_id)
            ->orderBy("sort")
            ->orderByDesc('id')
            ->paginate($limit)
            ->toArray();

        return $res;
    }

    /**
     * 获取电子书资源列表
     * @param ebook_id 电子书id
     */
    public function getChapterInfo($ebook_id)
    {
        //获取章节列表
        $chapter_Info = $this->where('ebook_id', $ebook_id)->orderBy("sort")->get()->toArray();
        //处理章节信息
        $chapter_Info = $this->checkChapterInfo($chapter_Info);

        return $chapter_Info;
    }

    /**
     * 根据电子书id获取章节信息   无限分类获取数据
     * $maxNum  设置最大循环次数   可以用等级作为最大循环次数
     */
    public function checkChapterInfo($chapter_Info)
    {
        //获取序列化值
        $chapter_Info_serialize = serialize($chapter_Info);
        $chapter_Info_data = Cache::get($chapter_Info_serialize);
        if ($chapter_Info_data) {
            return unserialize($chapter_Info_data); //反序列化返回
        }
        //结果记录的长度
        $len = count($chapter_Info);

        // $maxNum = 1000;//设置最大循环次数
        $maxNum = 3.5 * $len; //设置最大循环次数为记录长度的3.5倍

        $count = -1; //设置计数
        //未根节点内容
        $root = array(
            'id' => '0',
            'chapter_name' => 'root',
            'chapter_src' => 'root',
            'chapter_id' => 'root',
            'sort' => 'root',
        );
        //辅助，主要作用用于检测节点是否存在
        //注：下面使用的技巧都是使用对象的引用，赋值的不是一个具体值，而是一个引用
        $existsMap = array(
            '0' => &$root,
        );

        //计数
        $num = 0;
        //遍历结果集
        while ($num < $len) {
            $count++;
            //如果计数器超过了最大循环次数就退出循环
            if ($count > $maxNum) break;
            $i = $count % $len; //取得下标，取模的作用是防止下标超出边界
            $obj = $chapter_Info[$i]; //取得当前节点
            if (!$obj) continue; //不存在则跳过
            $pidObj = &$existsMap[$obj['pid']]; //检测辅助数组中是否有父节点数据并赋引用值给pidObj
            if (!$pidObj) continue;
            //如果存在pidObj，则设置当前节点在existsMap中
            $existsMap[$obj['id']] = array(
                'id' => $obj['id'],
                'chapter_name'      => $obj['chapter_name'],
                'chapter_src'       => $obj['chapter_src'],
                'chapter_id'        => $obj['chapter_id'],
                'sort' => $obj['sort'],
            );
            //设置子节点
            if (empty($pidObj['children'])) {
                $pidObj['children'] = array();
            }
            //设置子节点为刚刚存在辅助数组中得引用
            $pidObj['children'][] = &$existsMap[$obj['id']];
            unset($chapter_Info[$i]);
            $num++;
        }

        //序列化存储
        $root['children'] = isset($root['children']) ? $root['children'] : [];
        $children = serialize($root['children']);
        Cache::put($chapter_Info_serialize, $children, 24 * 60 * 60 * 7); //缓存一个星期

        //根据自己的需求，决定是否返回root节点
        return $root['children'];
    }

    /**
     * 根据电子书章节链接，获取电子书章节数据
     * @param chapter_src  章节链接
     */
    public function getChapterInfoBySrc($chapter_src)
    {
        $chapter_src = explode("#", $chapter_src)[0]; //有些链接 是锚点定位的链接
        $src = config('server_host_url') . 'Uploads/' . $chapter_src;
        $data = file_get_contents($src);
        $img_addr = explode("/", $chapter_src);
        array_pop($img_addr); //删除数组最后一个元素
        array_pop($img_addr); //删除数组最后一个元素（在删除一个）
        $img_addr = config('server_host_url') . 'Uploads/' . join("/", $img_addr);

        if ($data) {
            /* $data = preg_replace("/<img.*?>/i", '',$data);*/
            $data = preg_replace('~<img.*?src="..(.*?)".*?/>~ism', '<img src="' . $img_addr . '$1" alt=\' \' />', $data); //图片匹配加上前缀
            preg_match_all("~<body.*?>(.*?)</body>~ius", $data, $content); //只需要body部分
            if (isset($content[0][0]) || !empty($content[0][0])) {
                return $content[0][0];
            }
            return false;
        } else {
            return false;
        }
    }
}
